package edu.washington.ling.syntric.io;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import edu.stanford.nlp.util.StringUtils;
import edu.washington.ling.syntric.struct.rule.*;
import edu.washington.ling.syntric.struct.tree.Node;
import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.util.LaTeXUtils;
import edu.washington.ling.syntric.util.Utils;

public class RuleWriterLaTeX extends RuleWriter{

	TreeWriterLaTeX tw = new TreeWriterLaTeX();
	
	private String writeToken(Token t) {
		String tag = t.getTag();
		ArrayList<String> fvStrs = new ArrayList<String>();
		for (String feat: t.getFeatures()) {
			if (!t.isDerrived(feat)) {
				String val = t.getValue(feat);
				feat = LaTeXUtils.formatForLabel(feat);
				val = LaTeXUtils.formatForLabel(val);
				fvStrs.add(String.format("%s=%s", feat, val));
			}
		}
		return String.format("%s $<$fs %s$>$", tag, Utils.join(fvStrs, " "));
	}
	
	private String writeNode(Node n) {
		String label = n.getLabel();
		return label;
	}
	@Override
	public String writeUnaryDSPattern(UniDSPattern dsPatt) {
		Token dsToken = dsPatt.getDSToken();
		return String.format("[%s]", writeToken(dsToken));
	}
	
	private String writeUnaryPSPattern(UniPSPattern psPatt) {
		ArrayList<String> nodeStrs = new ArrayList<String>();
		for (Node psNode: psPatt.getRootChain()) {
			nodeStrs.add(writeNode(psNode));
		}
		return String.format("[%s]", Utils.join(nodeStrs, " "));
	}
	@Override
	public String writeBinaryDSPattern(BiDSPattern dsPatt) {
		String dsChildStr = writeToken(dsPatt.getDSDependent());
		String dsParentStr = writeToken(dsPatt.getDSHead());
		String dsPatternStr = String.format("[%s] [%s]", dsChildStr, dsParentStr);
		if (dsPatt.hasHeadOrder()) {
			if (dsPatt.isHeadFinal()) {
				dsPatternStr = String.format("[%s] \\textbf{[%s]}", dsChildStr, dsParentStr);
			}
			else {
				dsPatternStr = String.format("\\textbf{[%s]} [%s]", dsChildStr, dsParentStr);
			}
		}
		return dsPatternStr;
	}
	private String writeBinaryPSPattern(BiPSPattern psPatt) {
		List<String> psRootStrs = new LinkedList<String>();
		for (Node psRootElem: psPatt.getRootChain()) {
			psRootStrs.add(psRootElem.getLabel());
		}
		String psDepChildStr = writeNode(psPatt.getDepChild());
		String psHeadChildStr = writeNode(psPatt.getHeadChild());
		return String.format("(%s (%s %s))", StringUtils.join(psRootStrs, " "), psDepChildStr, psHeadChildStr);
	}

	
	@Override
	public RuleRepresentation writeUnaryRule(UniRule rule) {
		String dsPattStr = writeUnaryDSPattern(rule.getDSPattern());
		String psPattStr = writeUnaryPSPattern(rule.getPSPattern());
		return new RuleRepresentation(dsPattStr, psPattStr);
	}

	@Override
	public RuleRepresentation writeBinaryRule(BiRule rule) {
		String dsPattStr = writeBinaryDSPattern(rule.getDSPattern());
		String psPattStr = writeBinaryPSPattern(rule.getPSPattern());
		return new RuleRepresentation(dsPattStr, psPattStr);
	}

}
